/**
 * 
 */
package com.glela.common.util;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.Converter;
import org.springframework.cglib.beans.BeanCopier;

import com.glela.common.constant.BaseConstants;

/**
 * @author liujie
 *
 */
public class BeanCopierUtils {
	
	public static Map<String,BeanCopier> beanCopierMap = new HashMap<String,BeanCopier>();
    
    public static void copy(Object source, Object target){
        String beanKey =  generateKey(source.getClass(), target.getClass());
        BeanCopier copier =  null;
        if(!beanCopierMap.containsKey(beanKey)){
             copier = BeanCopier.create(source.getClass(), target.getClass(), false);
             beanCopierMap.put(beanKey, copier);
        }else{
             copier = beanCopierMap.get(beanKey);
        }
        copier.copy(source, target, null);
    }   
    
    private static String generateKey(Class<?> class1,Class<?>class2){
        return class1.toString() + class2.toString();
    }
    
    
    public static Map<String, String> objectToMap(Object obj)  {      
        if(obj == null){      
            return null;      
        }     
        Map<String, String> map = new HashMap<String, String>();      
        Field[] declaredFields = obj.getClass().getDeclaredFields();      
        try {
        	for (Field field : declaredFields) {      
                field.setAccessible(true); 
                if(field.get(obj) != null) {
                	if(field.getType() == Date.class || field.getType() == Timestamp.class) {
                		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
                		map.put(field.getName(), sdf.format(field.get(obj)));
                	}else {
                		map.put(field.getName(), String.valueOf(field.get(obj)));
                	}
                	
                }
            }
        } catch(Exception e) {
        	e.printStackTrace();
        }  
     
        return map;    
    }     
    
    
    public static Map<String,String> beanToMap(Object bean){
        try {
        	return BeanUtils.describe(bean);
        } catch(Exception e) {
        	e.printStackTrace();
        }
        return null;
    }  
    /** 
     * map 转化为 bean 
     * @param clazz 
     * @param map 
     * @return 
     */
    
    public static <T> T mapToBean(Map<String, Object> map, Class<T> class1) {  
        T bean = null;  
        try {  
            bean = class1.newInstance();  
            BeanUtils.populate(bean, map);  
        } catch (InstantiationException e) {  
            e.printStackTrace();  
        } catch (IllegalAccessException e) {  
            e.printStackTrace();  
        } catch (InvocationTargetException e) {  
            e.printStackTrace();  
        }  
        return bean;  
    } 
    
    
    
    /** 
     *  
     *  
     * Map转换层Bean，使用泛型免去了类型转换的麻烦。 
     * @param <T> 
     * @param map   
     * @param class1 
     * @return 
     */  
    public static <T> T map2Bean(Map<String, String> map, Class<T> class1) {  
        T bean = null;  
        try {  
        	if(map == null || map.isEmpty()) {
        		return bean;
        	}
        	
            bean = class1.newInstance(); 
            ConvertUtils.register(new DateConverter(), java.util.Date.class); 
            BeanUtils.populate(bean, map);  
        } catch (InstantiationException e) {  
            e.printStackTrace();  
        } catch (IllegalAccessException e) {  
            e.printStackTrace();  
        } catch (InvocationTargetException e) {  
            e.printStackTrace();  
        }  
        return bean;  
    }  
    
    
    public static <T> T map2Obj(Map<String,String> map,Class<T> clz) {
        if (map == null)           return null;  
        try {
        	T obj = clz.newInstance(); 
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());  
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();  
            for (PropertyDescriptor property : propertyDescriptors) { 
              Method setter = property.getWriteMethod();  
              if (setter != null) { 
                setter.invoke(obj, map.get(property.getName()));  
              } 
            } 
            return obj;
        }catch(Exception e) {
        	e.printStackTrace();
        }
        return null;
      }
    
    
    
    
}
